package com.todo.user.application.frontend.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.todo.common.common.entity.response.BizResponse;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.DateUtils;
import com.todo.user.application.convert.UserInfoConvert;
import com.todo.user.application.entity.bo.FollowFriendBO;
import com.todo.user.application.entity.bo.FollowFriendInfoBO;
import com.todo.user.application.entity.bo.UserInfoDetailBO;
import com.todo.user.application.entity.bo.UserSimplyInfoBO;
import com.todo.user.application.frontend.model.BatchQuerySimplyUserInfoModel;
import com.todo.user.application.frontend.service.UserInfoAggService;
import com.todo.user.application.service.UserAccountService;
import com.todo.user.application.service.UserInfoService;
import com.todo.user.application.service.UserRelationService;
import com.todo.user.common.enums.FriendTypeEnum;
import com.todo.user.iface.frontend.request.*;
import com.todo.user.iface.frontend.response.BaseUserDetailVO;
import com.todo.user.iface.frontend.response.UserDetailVO;
import com.todo.user.iface.frontend.response.UserRelationVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhangwenxiang
 * @date 2024/4/9 11:46
 * @description
 */
@Slf4j
@Service
public class UserInfoAggServiceImpl implements UserInfoAggService {

    @Resource
    private UserAccountService userAccountService;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private UserRelationService userRelationService;


    @Override
    public BizResponse<BaseUserDetailVO> queryOtherUserInfoDetail(QueryOtherUserDetailParam param) {
        if (param == null) {
            return BizResponse.success();
        }
        Long currentUserId = param.get_user().getUserId();
        Long otherUserId = param.getOtherUserId();

        UserInfoDetailBO userInfoDetailBO = userInfoService.queryUserInfoDetailById(otherUserId);
        if (userInfoDetailBO == null) {
            log.error("UserInfoService#queryOtherUserInfoDetail 查询用户详情为空 userId:【{}】", otherUserId);
            return BizResponse.operationFailed("当前用户不存在");
        }
        BaseUserDetailVO userDetailVO = UserInfoConvert.buildBaseUserDetailVOByResponse(userInfoDetailBO);
        //查询用户关联信息构建返回结果
        FollowFriendInfoBO followFriendInfoBO = userRelationService.queryOtherUserInfoDetail(currentUserId, otherUserId);
        FollowFriendInfoBO otherFollowFriendInfoBO = userRelationService.queryOtherUserInfoDetail(otherUserId, currentUserId);

        fillRelationInfo(userDetailVO, followFriendInfoBO, otherFollowFriendInfoBO);
        return BizResponse.success(userDetailVO);
    }

    @Override
    public BizResponse<UserDetailVO> queryUserDetail(QueryUserDetailParam param) {
        if (param == null) {
            return BizResponse.success();
        }
        UserInfoDetailBO userInfoDetailBO = userInfoService.queryUserInfoDetailById(param.get_user().getUserId());
        UserDetailVO userDetailVO = UserInfoConvert.convertToUserDetailVO(userInfoDetailBO);
        return BizResponse.success(userDetailVO);
    }

    @Override
    public BizResponse<Boolean> updateUserDetail(UserDetailParam param) {
        if (param == null || param.get_user() == null) {
            return BizResponse.operationFailed();
        }
        UserInfoDetailBO userInfoDetailBO = UserInfoConvert.convertToUserInfoDetailBO(param);
        Boolean updateResult = userInfoService.updateUserInfoDetail(userInfoDetailBO);
        return BizResponse.success(updateResult);
    }

    @Override
    public BizResponse<Boolean> saveUserRelation(SaveUserRelationParam param) {
        if (param == null) {
            return BizResponse.success();
        }
        FollowFriendInfoBO followFriendInfoBO = FollowFriendInfoBO.builder()
                .userId(param.get_user().getUserId())
                .relationUserId(param.getRelationUserId())
                .friendType(FriendTypeEnum.getByType(param.getFriendType()))
                .operateReason("主动添加好友")
                .build();
        Boolean result = userRelationService.followFriend(followFriendInfoBO);
        return BizResponse.success(result);
    }

    @Override
    public PageResult<UserRelationVO> queryUserRelationList(UserRelationListParam param) {
        FollowFriendBO followFriendBO = UserInfoConvert.convertToUserRelationListRequest(param);
        PageResult<FollowFriendInfoBO> result = userRelationService.followFriendsList(followFriendBO);
        if (result == null || CollectionUtils.isEmpty(result.getResults())) {
            log.warn("UserInfoAggService#queryUserRelationList 查询用户关联信息完成，数据为空，默认返回 param:【{}】", JSONObject.toJSONString(param));
            return PageResult.of(Lists.newArrayList(), param.getPageIndex(), param.getPageSize(), 0, 0);
        }
        //获取用户基础信息
        List<Long> userIdlList = result.getResults()
                .stream()
                .map(FollowFriendInfoBO::getRelationUserId)
                .collect(Collectors.toList());
        BatchQuerySimplyUserInfoModel response = batchQuerySimplyUserInfo(userIdlList);
        PageResult<UserRelationVO> userRelationVOPageResult = new PageResult<>();
        userRelationVOPageResult.setResults(UserInfoConvert.buildUserRelationVOList(result.getResults(), response));
        userRelationVOPageResult.setTotal(result.getTotal());
        userRelationVOPageResult.setHasNext(result.isHasNext());
        userRelationVOPageResult.setCurrentIndex(result.getCurrentIndex());
        userRelationVOPageResult.setPageCount(result.getPageCount());
        userRelationVOPageResult.setPageSize(result.getPageSize());
        userRelationVOPageResult.setPageNum(result.getPageNum());
        return userRelationVOPageResult;
    }

    @Override
    public BizResponse<Boolean> updateUserHeadImg(UserHeadImgParam param) {
        if (param == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        Boolean result = userInfoService.updateUserHeadImg(param.get_user().getUserId(), param.getHeadImg());
        return BizResponse.success(result);
    }

    /**
     * 批量查询用户基础信息
     *
     * @param userIdList
     * @return
     */
    public BatchQuerySimplyUserInfoModel batchQuerySimplyUserInfo(List<Long> userIdList) {
        List<UserSimplyInfoBO> userSimplyInfoBOS = userInfoService.batchQuerySimplyUserInfo(userIdList);
        BatchQuerySimplyUserInfoModel response = new BatchQuerySimplyUserInfoModel();
        if (CollectionUtils.isEmpty(userSimplyInfoBOS)) {
            response.setMissedUsrId(userIdList);
            return response;
        }

        List<Long> failedUserIdList = new ArrayList<>();
        Map<Long, UserSimplyInfoBO> userSimplyInfoBOMap = userSimplyInfoBOS
                .stream()
                .collect(Collectors.toMap(UserSimplyInfoBO::getUserId, Function.identity()));

        Map<Long, BatchQuerySimplyUserInfoModel.SimplyUserInfo> simplyUserInfoMap = new HashMap<>();
        for (Long userId : userIdList) {
            UserSimplyInfoBO userSimplyInfoBO = userSimplyInfoBOMap.get(userId);
            if (userSimplyInfoBO == null) {
                failedUserIdList.add(userId);
                continue;
            }
            BatchQuerySimplyUserInfoModel.SimplyUserInfo simplyUserInfo = new BatchQuerySimplyUserInfoModel.SimplyUserInfo();
            simplyUserInfo.setUserId(userId);
            simplyUserInfo.setUserName(userSimplyInfoBO.getUserName());
            simplyUserInfo.setGender(userSimplyInfoBO.getGender());
            simplyUserInfo.setUserNikeName(userSimplyInfoBO.getNickName());
            simplyUserInfo.setUserAvatar(userSimplyInfoBO.getHeadImg());
            simplyUserInfo.setLocation(userSimplyInfoBO.getLocation());
            simplyUserInfoMap.put(userId, simplyUserInfo);
        }
        if (CollectionUtils.isNotEmpty(failedUserIdList)) {
            log.info("UserInfoService#batchQuerySimplyUserInfo 批量查询用户信息，部分数据缺失 failedUserIdList：【{}】", JSONObject.toJSONString(failedUserIdList));
        }
        response.setMissedUsrId(failedUserIdList);
        response.setSimplyUserInfoMap(simplyUserInfoMap);
        return response;
    }

    /**
     * 填充关联关系
     *
     * @param userDetailVO
     * @param currentFollowFriendInfoBO
     * @param otherFollowFriendInfoBO
     * @return
     */
    private void fillRelationInfo(BaseUserDetailVO userDetailVO, FollowFriendInfoBO currentFollowFriendInfoBO, FollowFriendInfoBO otherFollowFriendInfoBO) {

        //都不为空则为好友
        if (currentFollowFriendInfoBO != null && otherFollowFriendInfoBO != null) {
            userDetailVO.setFriendType(FriendTypeEnum.FRIENDS.getName());
            Date curTime = currentFollowFriendInfoBO.getCreateTime();
            Date othTime = otherFollowFriendInfoBO.getCreateTime();
            Date operateTime = curTime.after(othTime) ? curTime : othTime;
            int diffDay = DateUtils.differentDaysByMillisecond(new Date(), operateTime);
            userDetailVO.setRelationTime(diffDay);
            return;
        }

        //都为空则为普通关系
        if (currentFollowFriendInfoBO == null && otherFollowFriendInfoBO == null) {
            userDetailVO.setFriendType(FriendTypeEnum.NONE.getName());
            return;
        }
        //被关注
        if (otherFollowFriendInfoBO != null) {
            userDetailVO.setFriendType(FriendTypeEnum.FOLLOWED.getName());
            int diffDay = DateUtils.differentDaysByMillisecond(new Date(), otherFollowFriendInfoBO.getCreateTime());
            userDetailVO.setRelationTime(diffDay);
            return;
        }
        //关注对方
        userDetailVO.setFriendType(FriendTypeEnum.FOLLOW.getName());
        int diffDay = DateUtils.differentDaysByMillisecond(new Date(), currentFollowFriendInfoBO.getCreateTime());
        userDetailVO.setRelationTime(diffDay);

    }
}
